//
//  BTEDeviceInfomationManager.swift
//  BTE
//
//  Created by Mike Zhang on 2025/8/5.
//

import UIKit

import Foundation
import SystemConfiguration.CaptiveNetwork
import SystemConfiguration
import CoreTelephony
import UIKit
import AdSupport

// MARK: - WiFi 信息
struct WiFiInfo {
    static func getCurrentSSID() -> String? {
        return fetchWiFiInfo()?.ssid
    }

    static func getCurrentBSSID() -> String? {
        return fetchWiFiInfo()?.bssid
    }

    private static func fetchWiFiInfo() -> (ssid: String?, bssid: String?)? {
        guard let interfaces = CNCopySupportedInterfaces() as? [String],
              let interface = interfaces.first,
              let info = CNCopyCurrentNetworkInfo(interface as CFString) as NSDictionary? else {
            return nil
        }

        let ssid = info[kCNNetworkInfoKeySSID as String] as? String
        let bssid = info[kCNNetworkInfoKeyBSSID as String] as? String
        return (ssid, bssid)
    }
}

// MARK: - 网络信息
struct NetworkInfo {
    static func getNetworkType() -> String {
        guard let reachability = createReachability() else { return "No Network" }
        var flags = SCNetworkReachabilityFlags()
        if !SCNetworkReachabilityGetFlags(reachability, &flags) {
            return "No Network"
        }
        if flags.contains(.reachable) {
            return flags.contains(.isWWAN) ? getCellularType() : "WiFi"
        }
        return "No Network"
    }

    private static func createReachability() -> SCNetworkReachability? {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        return withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        }
    }

    private static func getCellularType() -> String {
        let info = CTTelephonyNetworkInfo()
        let type: String?

        if #available(iOS 12.0, *) {
            type = info.serviceCurrentRadioAccessTechnology?.values.first
        } else {
            type = info.currentRadioAccessTechnology
        }

        guard let radio = type else { return "Unknown" }

        if #available(iOS 14.1, *), radio == CTRadioAccessTechnologyNR || radio == CTRadioAccessTechnologyNRNSA {
            return "5G"
        }

        switch radio {
        case CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge, CTRadioAccessTechnologyCDMA1x:
            return "2G"
        case CTRadioAccessTechnologyWCDMA, CTRadioAccessTechnologyHSDPA, CTRadioAccessTechnologyHSUPA,
             CTRadioAccessTechnologyeHRPD, CTRadioAccessTechnologyCDMAEVDORev0,
             CTRadioAccessTechnologyCDMAEVDORevA, CTRadioAccessTechnologyCDMAEVDORevB:
            return "3G"
        case CTRadioAccessTechnologyLTE:
            return "4G"
        default:
            return "Unknown"
        }
    }

    static func isUsingProxy() -> Bool {
        guard let settings = CFNetworkCopySystemProxySettings() as? [String: Any],
              let enabled = settings[kCFNetworkProxiesHTTPEnable as String] as? NSNumber,
              let proxy = settings[kCFNetworkProxiesHTTPProxy as String] as? String else {
            return false
        }
        return enabled.boolValue && !proxy.isEmpty
    }

    static func isVPNEnabled() -> Bool {
        guard let settings = CFNetworkCopySystemProxySettings() as? [String: Any],
              let scoped = settings["__SCOPED__"] as? [String] else {
            return false
        }
        return scoped.contains { $0.contains("tap") || $0.contains("tun") || $0.contains("ppp") || $0.contains("ipsec") }
    }
}

// MARK: - 存储信息
struct StorageInfo {
    static func getAvailable() -> Int64 {
        let url = URL(fileURLWithPath: NSTemporaryDirectory())
        let value = try? url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
        return value?.volumeAvailableCapacityForImportantUsage ?? -1
    }

    static func getTotal() -> Int64 {
        if let attrs = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()),
           let size = attrs[.systemSize] as? Int64 {
            return size
        }
        return 0
    }
    
    static func getPhysicalMemorySize() -> String {
        return "\(ProcessInfo.processInfo.physicalMemory)"
    }

    static func getAvailableMemorySize() -> String {
        var stats = vm_statistics64()
        var count = mach_msg_type_number_t(MemoryLayout.size(ofValue: stats) / MemoryLayout<integer_t>.size)

        let result = withUnsafeMutablePointer(to: &stats) {
            $0.withMemoryRebound(to: Int32.self, capacity: Int(count)) {
                host_statistics64(mach_host_self(), HOST_VM_INFO64, $0, &count)
            }
        }

        guard result == KERN_SUCCESS else { return "0" }

        let pageSize = Int64(vm_kernel_page_size)
        let available = Int64(stats.free_count + stats.inactive_count) * pageSize
        return "\(available)"
    }
}

// MARK: - 设备信息
struct DeviceInfo {
    static func getSystemVersion() -> String { UIDevice.current.systemVersion }
    static func getModelIdentifier() -> String {
        var systemInfo = utsname()
        uname(&systemInfo)
        return withUnsafeBytes(of: &systemInfo.machine) {
            $0.compactMap { $0 != 0 ? String(UnicodeScalar(UInt8($0))) : nil }.joined()
        }
    }

    static func isSimulator() -> Bool {
#if targetEnvironment(simulator)
        return true
#else
        return false
#endif
    }

    static func isJailbroken() -> Bool {
        FileManager.default.fileExists(atPath: "/private/var/lib/apt/")
    }

    static func getTimeZone() -> String {
        TimeZone.current.identifier
    }

    static func getPreferredLanguage() -> String {
        Locale.preferredLanguages.first ?? "en"
    }
}

// MARK: - 电池信息
struct BatteryInfo {
    static func getLevel() -> Int {
        UIDevice.current.isBatteryMonitoringEnabled = true
        return Int(UIDevice.current.batteryLevel * 100)
    }

    static func isCharging() -> Bool {
        UIDevice.current.isBatteryMonitoringEnabled = true
        return UIDevice.current.batteryState == .charging || UIDevice.current.batteryState == .full
    }
}

// MARK: - 汇总工具
class DeviceInfoCollector {
    
    static let server = BTEUploadToolNetServer()
    
    static func collectSummary(completion: @escaping (String) -> Void) {
        let summary: [String: Any] = [
            "unflying": [
                "unharnessed": StorageInfo.getAvailable(),
                "puccini": StorageInfo.getTotal(),
                "tenontotomy": StorageInfo.getPhysicalMemorySize(),
                "inextirpable": StorageInfo.getAvailableMemorySize(),
            ],
            "sibella": [
                "bartramian": BatteryInfo.getLevel(),
                "airports": BatteryInfo.isCharging() ? 1 : 0
            ],
            "cysts": [
                "pennyan": DeviceInfo.getSystemVersion(),
                "redeceive": UIDevice.current.types.rawValue,
                "hexact": DeviceInfo.getModelIdentifier()
            ],
            "amphipyrenin": [
                "unlooped": DeviceInfo.isSimulator() ? 1 : 0,
                "derider": DeviceInfo.isJailbroken() ? 1 : 0
            ],
            "lamdin": [
                "salicylate": DeviceInfo.getTimeZone(),
                "augh":BTEDeviceIdentifierManager.shared.vendorID(),
                "jeopardised": DeviceInfo.getPreferredLanguage(),
                "tailback":BTEDeviceIdentifierManager.shared.advertisingID(),
                "erymanthus":NetworkInfo.getNetworkType()
            ],
            "hisbe":[
                "ahoys":[
                    "manificum":WiFiInfo.getCurrentSSID() ?? "", //mac
                    "thorough":WiFiInfo.getCurrentBSSID() ?? "", //name
                ]
            ],
        ]
        
        if let jsonData = try? JSONSerialization.data(withJSONObject: summary, options: .prettyPrinted),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            completion(jsonString)
        }
    }
    
    
    static func uploadInfomation(_ data: String){
        server.blytheville(data: ["sidelingwise":data]) { result in
            switch result {
            case .success(let success):
                print("上传设备信息成功")
                break
            case .failure(let failure):
                print("上传设备信息失败")
                break
            }
        }
    }
    
}
